package com.zzyl.nursing.service.impl;

import java.util.List;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.IdcardUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.zzyl.common.exception.base.BaseException;
import com.zzyl.common.utils.CodeGenerator;
import com.zzyl.common.utils.DateUtils;
import com.zzyl.nursing.domain.*;
import com.zzyl.nursing.dto.*;
import com.zzyl.nursing.mapper.*;
import com.zzyl.nursing.service.ICheckInConfigService;
import com.zzyl.nursing.vo.CheckInConfigVo;
import com.zzyl.nursing.vo.CheckInDetailVo;
import com.zzyl.nursing.vo.CheckInElderVo;
import com.zzyl.nursing.vo.ElderFamilyVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.zzyl.nursing.service.ICheckInService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.transaction.annotation.Transactional;

import java.util.Arrays;

/**
 * 入住信息Service业务层处理
 * 
 * @author ruoyi
 * @date 2025-09-08
 */
@Service
public class CheckInServiceImpl extends ServiceImpl<CheckInMapper, CheckIn> implements ICheckInService
{
    @Autowired
    private CheckInMapper checkInMapper;
    @Autowired
    private ElderMapper elderMapper;
    @Autowired
    private BedMapper bedMapper;
    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private CheckInConfigMapper checkInConfigMapper;


    /**
     * 查询入住信息
     * 
     * @param id 入住信息主键
     * @return 入住信息
     */
    @Override
    public CheckIn selectCheckInById(Long id)
    {
        return getById(id);
    }

    /**
     * 查询入住信息列表
     * 
     * @param checkIn 入住信息
     * @return 入住信息
     */
    @Override
    public List<CheckIn> selectCheckInList(CheckIn checkIn)
    {
        return checkInMapper.selectCheckInList(checkIn);
    }

    /**
     * 新增入住信息
     * 
     * @param checkIn 入住信息
     * @return 结果
     */
    @Override
    public int insertCheckIn(CheckIn checkIn)
    {
        return save(checkIn) ? 1 : 0;
    }

    /**
     * 修改入住信息
     * 
     * @param checkIn 入住信息
     * @return 结果
     */
    @Override
    public int updateCheckIn(CheckIn checkIn)
    {
        return updateById(checkIn) ? 1 : 0;
    }

    /**
     * 批量删除入住信息
     * 
     * @param ids 需要删除的入住信息主键
     * @return 结果
     */
    @Override
    public int deleteCheckInByIds(Long[] ids)
    {
        return removeByIds(Arrays.asList(ids)) ? 1 : 0;
    }

    /**
     * 删除入住信息信息
     * 
     * @param id 入住信息主键
     * @return 结果
     */
    @Override
    public int deleteCheckInById(Long id)
    {
        return removeById(id) ? 1 : 0;
    }

    /**
     * 新增申请入住表信息
     */
    @Override
    @Transactional
    public void apply(CheckInApplyDto applyDto) {
        // 0. 准备工作；列出所有信息项
        CheckInElderDto elderInfo = applyDto.getCheckInElderDto(); // 老人信息
        List<ElderFamilyDto> familyInfo = applyDto.getElderFamilyDtoList(); // 老人家属信息
        CheckInConfigDto checkInInfo = applyDto.getCheckInConfigDto(); // 入住信息
        CheckInContractDto contractInfo = applyDto.getCheckInContractDto(); // 合同签约信息

        // 1. 校验老人的信息是否已存在，且入住状态为1，如果是，则提示（抛异常）
        LambdaQueryWrapper<Elder> wrapper = Wrappers.<Elder>lambdaQuery()
                .eq(Elder::getIdCardNo, elderInfo.getIdCardNo())
                .eq(Elder::getStatus, 1);
        Elder elder = elderMapper.selectOne(wrapper);
        if (ObjectUtil.isNotEmpty(elder)){
            throw new BaseException("该老人已入住，请勿重复操作！");
        }

        // 2. 如果老人没有入住，则更新床位状态为已入住（占床位）
        Bed bed = bedMapper.selectById(checkInInfo.getBedId());
        bed.setBedStatus(1);
        int result = bedMapper.updateById(bed);
        if (result == 0){ // 如果停留在页面时有其他人占了床位，则抛异常
            throw new BaseException("该床位已有人，请重新选择床位！");
        }

        // 3. 新增或更新老人信息
        elder = insertOrUpdateElder(elderInfo, checkInInfo, bed);

        // 4. 新增签约信息
        insertContract(contractInfo, elder, checkInInfo);

        // 5. 新增入住信息
        Long checkInId = InsertCheckIn(elder, checkInInfo, bed, familyInfo);

        // 6. 新增入住配置信息
        InsertCheckInConfig(checkInInfo, checkInId);

    }

    private void InsertCheckInConfig(CheckInConfigDto checkInInfo, Long checkInId) {
        // 1. 拷贝填充入住配置信息
        CheckInConfig checkInConfig = BeanUtil.toBean(checkInInfo, CheckInConfig.class);
        // 2. 填充入住id
        checkInConfig.setCheckInId(checkInId);
        // 3. 新增
        checkInConfigMapper.insert(checkInConfig);
    }

    private Long InsertCheckIn(Elder elder, CheckInConfigDto checkInInfo, Bed bed, List<ElderFamilyDto> familyInfo) {
        CheckIn checkIn = new CheckIn();
        // 1. 填充老人信息
        checkIn.setElderName(elder.getName());
        checkIn.setElderId(elder.getId());
        checkIn.setIdCardNo(elder.getIdCardNo());
        // 2. 填充入住信息
        checkIn.setStartDate(checkInInfo.getStartDate());
        checkIn.setEndDate(checkInInfo.getEndDate());
        checkIn.setNursingLevelName(checkInInfo.getNursingLevelName());
        // 3. 填充床位信息
        checkIn.setBedNumber(bed.getBedNumber());
        // 4. 填充家属信息
        if (ObjectUtil.isNotEmpty(familyInfo)){
            checkIn.setRemark(JSONUtil.toJsonStr(familyInfo));
        }
        checkInMapper.insert(checkIn);
        return checkIn.getId();
    }

    private void insertContract(CheckInContractDto contractInfo, Elder elder, CheckInConfigDto checkInInfo) {
        // 1. 拷贝填充合同签约信息
        Contract contract = BeanUtil.toBean(contractInfo, Contract.class);
        // 2. 填充老人信息
        contract.setElderId(elder.getId());
        contract.setElderName(elder.getName());
        // 3. 填充合同的开始和结束时间，合同编号
        contract.setStartDate(checkInInfo.getStartDate());
        contract.setEndDate(checkInInfo.getEndDate());
        contract.setContractName("HT"+ CodeGenerator.generateContractNumber());
        // 4. 新增
        contractMapper.insert(contract);
    }

    private Elder insertOrUpdateElder(CheckInElderDto elderInfo, CheckInConfigDto checkInInfo, Bed bed) {
        Elder elder;
        LambdaQueryWrapper<Elder> wrapper;
        // 3.1 将前端传入的老人信息拷贝填充到老人实体中
        elder = BeanUtil.toBean(elderInfo,Elder.class);
        // 3.2 填充实体中的床位信息
        elder.setBedId(checkInInfo.getBedId()); // 填充床位id
        elder.setBedNumber(bed.getBedNumber()); // 填充床位编号
        // 3.3 查询并判断老人是否曾经入住过（有记录且入住状态不等于1），是则修改，不是则新增
        wrapper = Wrappers.<Elder>lambdaQuery()
                .eq(Elder::getIdCardNo, elderInfo.getIdCardNo())
                .ne(Elder::getStatus, 1);
        Elder elderInDb = elderMapper.selectOne(wrapper);
        // 3.4 如果是，则为更新
        if (ObjectUtil.isNotEmpty(elderInDb)){
            elder.setStatus(1);
            elder.setId(elderInDb.getId());
            elderMapper.updateById(elder);
        } else {
            // 3.5 如果不是，则为新增
            elder.setStatus(1);
            elderMapper.insertElder(elder);
        }
        return elder;
    }

    /**
     * 查询入住详情
     * @param id 入住表(CheckIn)的主键
     * @return  一个封装了详细入住信息（入住表所有信息）的对象
     */
    @Override
    public CheckInDetailVo detail(Long id) {
        // 0.准备最终响应结果对象
        CheckInDetailVo checkInDetailVo = new CheckInDetailVo();
        // 1.准备入住配置信息的响应对象
        CheckInConfigVo checkInConfigVo = new CheckInConfigVo();
        CheckIn checkIn = checkInMapper.selectById(id); // 根据传入的入住表id查询入住表信息
        if (ObjectUtil.isNotEmpty(checkIn)){  // 如果查到的不为空，则将查到的信息拷贝到入住配置的响应对象中
            BeanUtil.copyProperties(checkIn, checkInConfigVo);
        }
        // 根据传入的入住表id查询对应的入住配置表中的信息
        CheckInConfig checkInConfig = checkInConfigMapper.selectOne(new LambdaQueryWrapper<CheckInConfig>().eq(CheckInConfig::getCheckInId, id));
        if (ObjectUtil.isNotEmpty(checkInConfig)){ // 如果查询到的不为空，则将查到的拷贝到入住配置的响应对象中
            BeanUtil.copyProperties(checkInConfig, checkInConfigVo);
        }
        // 将入住配置响应对象封装到最终的响应结果对象中
        checkInDetailVo.setCheckInConfigVo(checkInConfigVo);

        // 2. 设置老人信息的响应对象
        CheckInElderVo checkInElderVo = new CheckInElderVo();
        // 获取老人id(从我们查询到的入住表信息checkIn中可以拿到)
        Long elderId = checkIn.getElderId();
        Elder elder = elderMapper.selectById(elderId); // 根据老人id查询老人信息
        if (ObjectUtil.isNotEmpty(elder)){
            BeanUtil.copyProperties(elder,checkInElderVo);
        }
        // 填充老人的年龄,通过身份证号获取年龄，使用工具类IdcardUtil
        checkInElderVo.setAge(IdcardUtil.getAgeByIdCard(elder.getIdCardNo()));
        // 将老人对象封装到最终的响应结果对象中
        checkInDetailVo.setCheckInElderVo(checkInElderVo);

        // 3. 设置家属信息的响应对象
        String remark = checkIn.getRemark();
        if (StrUtil.isNotBlank(remark)){
            // 反序列化，将JSON格式的数据转成集合
            List<ElderFamilyVo> elderFamilyVos = JSON.parseArray(remark, ElderFamilyVo.class);
            checkInDetailVo.setElderFamilyVoList(elderFamilyVos);
        }

        // 4. 设置签约办理信息的响应对象
        // 根据老人id查询合同信息表，获取签约办理信息
        Contract contract = contractMapper.selectOne(new LambdaQueryWrapper<Contract>().eq(Contract::getElderId, elderId));
        // 将查询到的签约办理信息封装到最终的响应结果对象中
        checkInDetailVo.setContract(contract);

        return checkInDetailVo;
    }
}
